#include "uanalyserchannel.h"
#include "uanalyserrenderer.h"
#include "uanalysercontrols.h"
#include "uanalyserwidget.h"
#include "CommonDefs.h"

comboColorItem colorComboItems[] = {
    {QString("Red"), Qt::red},
    {QString("Dark Red"), Qt::darkRed},
    {QString("Green"), Qt::green},
    {QString("Dark Green"), Qt::darkGreen},
    {QString("Cyan"), Qt::cyan},
    {QString("Dark Cyan"), Qt::darkCyan},
    {QString("Magenta"), Qt::magenta},
    {QString("Dark Magenta"), Qt::darkMagenta},
    {QString("Yellow"), Qt::yellow},
    {QString("Dark Yellow"), Qt::darkYellow},
    {QString("Black"), Qt::black},
    {QString("Gray"), Qt::gray},
    {QString(), Qt::black}
};

comboNumberItem yGainComboItems[] = {
    {QString("5 V"), 5},
    {QString("2 V"), 2},
    {QString("1 V"), 1},
    {QString("0.5 V"), 0.5},
    {QString("0.2 V"), 0.2},
    {QString("0.1 V"), 0.1},
    {QString("0.05 V"), 0.05},
    {QString("0.02 V"), 0.02},
    {QString("0.01 V"), 0.01},
    {QString("5 mV"), 0.005},
    {QString("2 mV"), 0.002},
    {QString("1 mV"), 0.001},
    {QString(), -1}
};
const int defaultYGainIndex = 2;



/*******************************************
 * uAnalyserChannelTrace
 *******************************************/

uAnalyserChannelTrace::uAnalyserChannelTrace(QVector<double> *time_sweep, QVector<double> *v, double gain, double t_base, QColor col): timeSweep(time_sweep), voltage(v), yGain(gain), timeBase(t_base), yOffset(0), color(col)
{
    calculatePainterPath();
    setAcceptedMouseButtons(Qt::LeftButton);
}

void uAnalyserChannelTrace::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    QPen pen(color, 0, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin);
    painter->strokePath(painterPath, pen);
//    QPen pen2(QColor(0,0,0), 0, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin);
//    painter->strokePath(shapePath, pen2);
//    painter->setPen(pen2);
//    painter->drawRect(boundRect);
}

void uAnalyserChannelTrace::calculatePainterPath()
{
    double x_coord, y_coord;
    painterPath = QPainterPath();
    painterPath.moveTo(timeSweep->at(0)*40.0/timeBase, voltage->at(0)*40/yGain);

    /* calculate path for painting trace */
    for (int i=1; i<timeSweep->size(); ++i)
    {
        x_coord = timeSweep->at(i)*40.0/timeBase;
        y_coord = voltage->at(i)*40.0/yGain;
        painterPath.lineTo(x_coord, y_coord);
    }

    /* calculate surrounding band used for dragging traces with cursor -
       otherwise it would be necessary to point traces with pixel precision
     */
    /* below code assumes that samples are distributed evenly along time axis */
    const int margin_y = 5;
    const int margin_x = (margin_y*timeBase/40)*(timeSweep->size()-1)/(timeSweep->at(timeSweep->size()-1)-timeSweep->at(0));
    /* we are calculating margins if we have enough space to do this */
    if (2*(margin_y*timeBase/40) < (timeSweep->at(timeSweep->size()-1)-timeSweep->at(0)))
        {
        double v_temp;
        int i,j;
        shapePath = QPainterPath();
        shapePath.moveTo(timeSweep->at(margin_x)*40.0/timeBase, voltage->at(margin_x)*40.0/yGain);
        for (i=margin_x; i<=timeSweep->size()-margin_x-1; i++)
        {
            x_coord = timeSweep->at(i)*40.0/timeBase;
            v_temp = voltage->at(i-margin_x);
            for (j=-margin_x+1; j<=margin_x; j++ )
                if (v_temp < voltage->at(i+j))
                    v_temp = voltage->at(i+j);
            shapePath.lineTo(x_coord, v_temp*40.0/yGain + margin_y);
        }
        for (i=timeSweep->size()-margin_x-1; i>=margin_x; i--)
        {
            x_coord = timeSweep->at(i)*40.0/timeBase;
            v_temp = voltage->at(i-margin_x);
            for (j=-margin_x+1; j<=margin_x; j++ )
                if (v_temp > voltage->at(i+j))
                    v_temp = voltage->at(i+j);
            shapePath.lineTo(x_coord, v_temp*40.0/yGain - margin_y);
        }
        shapePath.closeSubpath();
        }
    else
        shapePath = painterPath;

    // in bounding rectalngle we have to take into consideration vertical margins size,
    // so mouse events on this trace could be handled properly
    boundRect = painterPath.controlPointRect();
    boundRect.adjust(0, -margin_y, 0, margin_y);
    // place trace in correct position in graphics view
    QTransform trace_transform;
    trace_transform.scale(1, -1);
    trace_transform.translate(-0.5*(boundRect.right()-boundRect.left()), yOffset*40/yGain);
    setTransform(trace_transform);
}

void uAnalyserChannelTrace::mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
{

    yOffset += (event->pos().y() - event->lastPos().y())*yGain/40.0;
    QTransform trace_transform;
    trace_transform.scale(1, -1);
    trace_transform.translate(-0.5*(boundRect.right()-boundRect.left()), yOffset*40/yGain);
    setTransform(trace_transform);
    update();
}


/*******************************************
 * uAnalyserChannel
 *******************************************/

uAnalyserChannel::uAnalyserChannel(uAnalyserControls *parent_container, uAnalyserWidget *main_widget, uAnalyserRenderer *rend, QVector<double> *time_sweep) :
    QWidget(parent_container), mainWidget(main_widget), renderer(rend), timeSweep(time_sweep)
{
    //create user interface for this channel
    channelGroupBox = new QGroupBox(this);
    channelGroupBox->setTitle(tr("Channel name"));

    colorCombo = new QComboBox();
    for (int i=0; colorComboItems[i].string != QString(); i++)
        colorCombo->addItem(colorComboItems[i].string, QVariant(colorComboItems[i].color));
    yGainCombo = new QComboBox();
    for (int i=0; yGainComboItems[i].string != QString(); i++)
        yGainCombo->addItem(yGainComboItems[i].string, QVariant(yGainComboItems[i].value));
    removeButton = new QPushButton("Remove");

    colorLabel = new QLabel("Color:");
    gainLabel = new QLabel("Gain:");
    vpdLabel = new QLabel("/ DIV");

    QGridLayout *channelLayout = new QGridLayout();
    channelGroupBox->setLayout(channelLayout);
    channelLayout->addWidget(colorLabel, 0, 0, Qt::AlignRight);
    channelLayout->addWidget(colorCombo, 0, 1);
    channelLayout->addWidget(gainLabel, 1, 0, Qt::AlignRight);
    channelLayout->addWidget(yGainCombo, 1, 1);
    channelLayout->addWidget(vpdLabel, 1, 2, Qt::AlignLeft);
    channelLayout->addWidget(removeButton, 2, 1);
    channelLayout->setSizeConstraint(QLayout::SetMinimumSize);

    int col = rand()%12;
    colorCombo->setCurrentIndex(col);
    yGainCombo->setCurrentIndex(defaultYGainIndex);


    //default trace is flat
    voltage.fill(0, timeSweep->size());
    //add trace of this channel to display
    trace = new uAnalyserChannelTrace(timeSweep, &voltage, yGainComboItems[defaultYGainIndex].value, mainWidget->getTimeBase() ,colorComboItems[col].color);
    renderer->addTrace(trace);

    connect(colorCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setColor(int)));
    connect(yGainCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(setYGain(int)));
    connect(removeButton, SIGNAL(clicked()), this, SLOT(remove()));
    connect(this, SIGNAL(removeChannelPressed()), main_widget, SLOT(removeChannel()));
    channelGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}

uAnalyserChannel::~uAnalyserChannel()
{
    renderer->removeTrace(trace);
    delete trace;
    delete channelGroupBox;
    voltage.clear();
}

void uAnalyserChannel::setColor(int i)
{
    trace->setColor(colorComboItems[i].color);
    renderer->update();
}

void uAnalyserChannel::setYGain(int i)
{
    trace->setYGain(yGainComboItems[i].value);
    recalculateTrace();
    renderer->update();
}

void uAnalyserChannel::setTimeBase(qreal time_base)
{
    trace->setTimeBase(time_base);
    recalculateTrace();
}

